# RS485串口管理模块 - 专门用于RS485设备通信

from driver import UART
import utime as time

# 全局RS485 UART对象
rs485_uart = None
RS485_STATUS = True

# 温度读取： 0B0400000002 7161
CMD_READ_TEMP = bytearray([0x0B, 0x04, 0x00, 0x00, 0x00, 0x02, 0x71, 0x61])
# 电压读取 65 03 00 00 00 06 CDEC
# 1：从地址0开始的6个变量，分别是A，B,C的三相电压和电流值
# 使用命令： 650300000006 CDEC(crcH,CRCL),
# 返回的数据65 03 0c  AB CD EF GH IJ KL MN OP QR ST UV WX   crcH,CRCL，
# A相电压=(AB*256+CD)/10  B相电压=(EF*256+GH)/10   C相电压=(IJ*256+KL)/10
# A相电流=(MN*256+OP)/100  B相电流=(QR*256+ST)/100   C相电流=(UV*256+WX)/100
CMD_READ_VOLT_CURRENT = bytearray([0x65, 0x03, 0x00, 0x00, 0x00, 0x06, 0xCD, 0xEC])
# 2：读取电量值使用命令 6503001D0002 5C29(crcH,CRCL),
# 返回的数据65 03 04  AB CD  EF GH crcH,CRCL，功耗=((AB*256+CD)*256+ (EF*256+GH))/100 KWH
CMD_READ_POWER = bytearray([0x65, 0x03, 0x00, 0x1D, 0x00, 0x02, 0x5C, 0x29])


def init():
    """初始化485模块"""
    print("[RS485] Initializing RS485 module...")
    return init_uart()


def start():
    """启动485模块"""
    print("[RS485] Starting RS485 module...")
    if rs485_uart:
        print("[RS485] RS485 module started successfully")
        return True
    else:
        print("[RS485] RS485 module start failed - UART not initialized")
        return False


def init_uart():
    # 初始化RS485 UART
    global rs485_uart

    if not RS485_STATUS:
        print("[RS485]RS485_STATUS disabled")
        return False

    try:
        rs485_uart = UART()
        rs485_uart.open("RS485")
        print("[RS485] RS485 UART initialized successfully")
        read_temperature_sensor()
        return True
    except Exception as e:
        print("[RS485] Failed to initialize RS485 UART: {}".format(e))
        return False


def cleanup_uart():
    # 清理RS485 UART资源
    global rs485_uart

    try:
        if rs485_uart:
            rs485_uart.close()
            print("[RS485] RS485 UART cleaned up successfully")
    except Exception as e:
        print("[RS485] Error during RS485 UART cleanup: {}".format(e))


def get_uart():
    # 获取UART对象
    return rs485_uart


# RS485总线设备调度管理
last_communication_time = 0
MIN_DEVICE_INTERVAL = 0.1  # 设备间最小通信间隔(秒)


def uart_write_read(command, read_delay=0.5, read_size=64):
    # UART写入并读取响应 - 增强版本，支持设备间通信调度
    global rs485_uart, last_communication_time

    if not rs485_uart:
        print("[UART] UART not initialized")
        return None

    # 设备间通信间隔管理，避免RS485总线冲突
    current_time = time.time()
    time_since_last = current_time - last_communication_time
    if time_since_last < MIN_DEVICE_INTERVAL:
        wait_time = MIN_DEVICE_INTERVAL - time_since_last
        time.sleep(wait_time)
        print("[UART] Device interval wait: {:.3f}s".format(wait_time))

    # print("[UART] Sending command: {}".format([hex(x) for x in command]))

    # 清空缓冲区 - 完全按照示例代码
    if rs485_uart.any() > 0:
        old_data = bytearray(50)
        bytes_cleared = rs485_uart.read(old_data)
        print("[UART] Cleared {} old bytes from buffer".format(bytes_cleared))

    # 发送命令 - 完全按照示例代码
    rs485_uart.write(command)
    # print("[UART] Command sent successfully")

    # 等待设备响应
    time.sleep(read_delay)

    # 读取响应 - 完全按照示例代码
    response = bytearray(read_size)
    bytes_received = rs485_uart.read(response)
    # print("[UART] Response received: {} bytes".format(bytes_received))

    # 更新最后通信时间
    last_communication_time = time.time()

    if bytes_received > 0:
        # 返回实际接收到的数据
        result = response[:bytes_received]
        # print("[UART] Response data: {}".format([hex(x) for x in result]))
        return result
    else:
        print("[UART] No response received")
        return None

# =============================================================================
# RS485设备统一管理接口 - 温度传感器和功率计
# =============================================================================


def read_temperature_sensor():
    # 读取温度传感器数据 (地址0x0B)
    if not rs485_uart:
        print("[UART_TEMP] RS485 UART not available")
        return None

    try:
        # Modbus RTU command: Read Input Registers
        # Address: 0x0B, Function: 0x04, Start: 0x0000, Count: 0x0002
        cmd = CMD_READ_TEMP

        response = uart_write_read(cmd, read_delay=0.5, read_size=9)

        if not response or len(response) < 9:
            print("[UART_TEMP] Invalid response length")
            return None

        # Validate response format
        if response[0] == 0x0B and response[1] == 0x04 and response[2] == 0x04:
            # Parse data bytes
            aa, bb, cc, dd = response[3], response[4], response[5], response[6]

            # Calculate temperature and humidity
            humidity = (aa * 256 + bb) / 10.0
            temperature = (cc * 256 + dd) / 10.0
            print(
                "[UART_TEMP] Temperature: {:.2f} C, Humidity: {:.2f} %".format(
                    temperature, humidity
                )
            )
            return {
                "temperature": temperature,
                "humidity": humidity,
            }
        else:
            print("[UART_TEMP] Invalid response format")
            return None

    except Exception as e:
        print("[UART_TEMP] Temperature read error: {}".format(e))
        return None


def read_power_voltage_current():
    # 读取功率计电压电流数据 (地址0x65)
    if not rs485_uart:
        print("[UART_POWER] RS485 UART not available")
        return None

    try:
        # Modbus RTU command: Read Holding Registers
        # Address: 0x65, Function: 0x03, Start: 0x0000, Count: 0x0006
        cmd = CMD_READ_VOLT_CURRENT

        response = uart_write_read(cmd, read_delay=0.5, read_size=17)

        if not response or len(response) < 17:
            print("[UART_POWER] Invalid V/I response length")
            return None

        # Validate response format
        if response[0] == 0x65 and response[1] == 0x03 and response[2] == 0x0C:
            # Extract 12 data bytes
            data_bytes = response[3:15]

            # Parse three-phase voltage and current
            voltage_a = ((data_bytes[0] << 8) | data_bytes[1]) / 10.0
            voltage_b = ((data_bytes[2] << 8) | data_bytes[3]) / 10.0
            voltage_c = ((data_bytes[4] << 8) | data_bytes[5]) / 10.0
            if(voltage_b ==0 and voltage_c==0):
                voltage_total = voltage_a
            else:
                voltage_total = (voltage_a + voltage_b + voltage_c)/3 * 1.73
            current_a = ((data_bytes[6] << 8) | data_bytes[7]) / 100.0
            current_b = ((data_bytes[8] << 8) | data_bytes[9]) / 100.0
            current_c = ((data_bytes[10] << 8) | data_bytes[11]) / 100.0
            current_total = (current_a + current_b + current_c) 
            print(
                "[UART_POWER] voltage: {:.2f} V,current: {:.2f} A , Voltage A: {:.2f} V, Voltage B: {:.2f} V, Voltage C: {:.2f} V, Current A: {:.2f} A, Current B: {:.2f} A, Current C: {:.2f} A".format(
                    voltage_total, current_total, voltage_a, voltage_b, voltage_c, current_a, current_b, current_c
                )
            )
            return {
                "voltage_a": voltage_a,
                "voltage_b": voltage_b,
                "voltage_c": voltage_c,
                "volt": voltage_total,
                "current_a": current_a,
                "current_b": current_b,
                "current_c": current_c,
                "current": current_total,
            }
        else:
            print("[UART_POWER] Invalid V/I response format")
            return None

    except Exception as e:
        print("[UART_POWER] V/I read error: {}".format(e))
        return None


def read_power_consumption():
    # 读取功率计能耗数据 (地址0x65)
    if not rs485_uart:
        print("[UART_POWER] RS485 UART not available")
        return None

    try:
        # Modbus RTU command: Read Holding Registers
        # Address: 0x65, Function: 0x03, Start: 0x001D, Count: 0x0002
        cmd = CMD_READ_POWER

        response = uart_write_read(cmd, read_delay=0.5, read_size=9)

        if not response or len(response) < 9:
            print("[UART_POWER] Invalid power response length")
            return None

        # Validate response format
        if response[0] == 0x65 and response[1] == 0x03 and response[2] == 0x04:
            # Extract 4 data bytes
            ab, cd, ef, gh = response[3], response[4], response[5], response[6]

            # Calculate power consumption
            # 功耗=((AB*256+CD)*256+ (EF*256+GH))/100 KWH
            power_kwh = ((ab * 256 + cd) * 256 + (ef * 256 + gh)) / 100.0

            print("[UART_POWER] Power: {:.2f} kWh".format(power_kwh))
            return power_kwh
        else:
            print("[UART_POWER] Invalid power response format")
            return None

    except Exception as e:
        print("[UART_POWER] Power read error: {}".format(e))
        return None


def read_complete_power_data():
    # 读取完整功率计数据（电压、电流、功耗）
    try:
        # 读取电压电流数据
        vi_data = read_power_voltage_current()
        if not vi_data:
            return None

        # 读取功耗数据
        power_consumption = read_power_consumption()
        if power_consumption is None:
            return None

        # 合并数据
        complete_data = vi_data.copy()
        complete_data["energy"] = power_consumption
        complete_data["timestamp"] = time.time()

        return complete_data

    except Exception as e:
        print("[UART_POWER] Complete power read error: {}".format(e))
        return None


# =============================================================================
# RS485设备数据读取接口完成
# =============================================================================
